﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionToWhere.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            int id = 2;
            string name = "aaabbb";
            string likeCondition = "%xxx";
            DateTime date = DateTime.Now;
            DateTime? nullDate = null;
            Worker temp = new Worker() { Id = 2, Name = "Guo", Age = 20 };
            string nullValue = null;

            #region ==、!=、>、>=、<、<=
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == 1 && worker.Id != 2 && worker.Id > 3 && worker.Id >= 4 && worker.Id < 5 && worker.Id <= 6;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == id && worker.Id != id && worker.Id > id && worker.Id >= id && worker.Id < id && worker.Id <= id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == temp.Id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == temp.Id && worker.Id != 1 + temp.Id * 5 + (int)(temp.Id / 3) && worker.Id > 1 + temp.Id * 5 + (int)(temp.Id / 3) && worker.Id >= 1 + temp.Id * 5 + (int)(temp.Id / 3) && worker.Id < 1 + temp.Id * 5 + (int)(temp.Id / 3) && worker.Id <= 1 + temp.Id * 5 + (int)(temp.Id / 3);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && worker.Id != 1 + Config.Id * 5 + (int)(Config.Id / 3) && worker.Id > 1 + Config.Id * 5 + (int)(Config.Id / 3) && worker.Id >= 1 + Config.Id * 5 + (int)(Config.Id / 3) && worker.Id < 1 + Config.Id * 5 + (int)(Config.Id / 3) && worker.Id <= 1 + Config.Id * 5 + (int)(Config.Id / 3);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == 1 + id * 5 + (int)(id / 3);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == 1 + id * 5 + (int)(id / 3) && worker.Id != 2 + id * 5 + (int)(id / 3) && worker.Id > 3 + id * 5 + (int)(id / 3) && worker.Id >= 4 + id * 5 + (int)(id / 3) && worker.Id < 5 + id * 5 + (int)(id / 3) && worker.Id <= 6 + id * 5 + (int)(id / 3); 
            //Expression<Func<Worker, bool>> expression = worker => worker.Name == Config.Name.Substring(0, 3) + "999";
            //Expression<Func<Worker, bool>> expression = worker => worker.Name == Config.Name.Substring(0, 3) + null;
            //Expression<Func<Worker, bool>> expression = worker => worker.Name == Config.Name.Substring(0, 3) + null + "999";
            #endregion

            #region !
            //Expression<Func<Worker, bool>> expression = worker => !(worker.Age == 1 + id * 5 + (int)(id / 3));
            //Expression<Func<Worker, bool>> expression = worker => !(worker.Age == 1 + id * 5 + (int)(id / 3)) && !(worker.Age != 2 + id * 5 + (int)(id / 3)) && !(worker.Age > 3 + id * 5 + (int)(id / 3)) && !(worker.Age >= 4 + id * 5 + (int)(id / 3)) && !(worker.Age < 5 + id * 5 + (int)(id / 3)) && !(worker.Age <= 6 + id * 5 + (int)(id / 3)); 
            //Expression<Func<Worker, bool>> expression = worker => !worker.Name.Equals("AAA");
            //Expression<Func<Worker, bool>> expression = worker => !worker.Name.In(new List<string>() { "a'aa", "bbb", "ccc" });
            //Expression<Func<Worker, bool>> expression = worker => !worker.Name.NotIn(new List<string>() { null, "", "aaa" });
            //Expression<Func<Worker, bool>> expression = worker => !worker.Name.StartsWith("%xxx") && !worker.Name.EndsWith("%xxx") && !worker.Name.Contains("%xxx");
            #endregion

            #region is null、is  not null、=="null"、!="null"
            //Expression<Func<Worker, bool>> expression = worker => worker.Name == null && worker.Name != null;
            //Expression<Func<Worker, bool>> expression = worker => worker.Name == "null" && worker.Name != "null"; 
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate >= null && worker.UpdateDate <= null;
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate >= nullDate && worker.UpdateDate <= nullDate;
            #endregion

            #region like_SqlServer
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith(null) && worker.Name.EndsWith(null) && worker.Name.Contains(null) && worker.Name.In(null) && worker.Name.In(new List<string>() { });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith("") && worker.Name.EndsWith(null) && worker.Name.Contains(null);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith("%xxx") && worker.Name.EndsWith("%xxx") && worker.Name.Contains("%xxx");
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith("") && worker.Name.EndsWith("%xxx" + null + "999") && worker.Name.Contains("%xxx" + null + "999");
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith(likeCondition) && worker.Name.EndsWith(likeCondition) && worker.Name.Contains(likeCondition);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith(likeCondition.Substring(0, 3) + "ext") && worker.Name.EndsWith(likeCondition.Substring(0, 3) + "ext") && worker.Name.Contains(likeCondition.Substring(0, 3) + "ext"); 
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.StartsWith("") && worker.Name.EndsWith("_xxx" + null + "999") && worker.Name.Contains("_xxx" + null + "999");
            #endregion

            #region like_MySql
            Expression<Func<Worker, bool>> expression01 = worker => worker.Name.StartsWith(null) && worker.Name.EndsWith(null) && worker.Name.Contains(null) && worker.Name.In(null) && worker.Name.In(new List<string>() { });
            Expression<Func<Worker, bool>> expression02 = worker => worker.Name.StartsWith("") && worker.Name.EndsWith(null) && worker.Name.Contains(null);
            Expression<Func<Worker, bool>> expression03 = worker => worker.Name.StartsWith("%xxx") && worker.Name.EndsWith("%xxx") && worker.Name.Contains("%xxx");
            Expression<Func<Worker, bool>> expression04 = worker => worker.Name.StartsWith("") && worker.Name.EndsWith("%xxx" + null + "999") && worker.Name.Contains("%xxx" + null + "999");
            Expression<Func<Worker, bool>> expression05 = worker => worker.Name.StartsWith(likeCondition) && worker.Name.EndsWith(likeCondition) && worker.Name.Contains(likeCondition);
            Expression<Func<Worker, bool>> expression06 = worker => worker.Name.StartsWith(likeCondition.Substring(0, 3) + "ext") && worker.Name.EndsWith(likeCondition.Substring(0, 3) + "ext") && worker.Name.Contains(likeCondition.Substring(0, 3) + "ext");
            #endregion

            #region int?、float?、double?、decimal?
            //Expression<Func<Worker, bool>> expression = worker => worker.Height1 == 1;
            //Expression<Func<Worker, bool>> expression = worker => worker.Height1 == null;
            //Expression<Func<Worker, bool>> expression = worker => worker.Height1 != null;
            //Expression<Func<Worker, bool>> expression = worker => worker.Height2 == 1.2f;
            //Expression<Func<Worker, bool>> expression = worker => worker.Height3 == 1.3;
            //Expression<Func<Worker, bool>> expression = worker => worker.Height4 == 1.4m; 
            #endregion

            #region DateTime
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate == null;
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate > null && worker.CreateDate < null && worker.CreateDate >= null && worker.CreateDate <= null;
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate == DateTime.Now;
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate == DateTime.Now && worker.CreateDate != DateTime.Now && worker.CreateDate > DateTime.Now && worker.CreateDate >= DateTime.Now && worker.CreateDate < DateTime.Now && worker.CreateDate <= DateTime.Now;
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate == date;
            //Expression<Func<Worker, bool>> expression = worker => worker.CreateDate == date && worker.CreateDate != date.AddDays(1) && worker.CreateDate > date.AddDays(2) && worker.CreateDate >= date.AddDays(3) && worker.CreateDate < date.AddDays(4) && worker.CreateDate <= date.AddDays(5); 
            #endregion

            #region DateTime?
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate == null;
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate > null && worker.UpdateDate < null && worker.UpdateDate >= null && worker.UpdateDate <= null;
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate == DateTime.Now;
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate == DateTime.Now && worker.UpdateDate != DateTime.Now && worker.UpdateDate > DateTime.Now && worker.UpdateDate >= DateTime.Now && worker.UpdateDate < DateTime.Now && worker.UpdateDate <= DateTime.Now; 
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate == date;
            //Expression<Func<Worker, bool>> expression = worker => worker.UpdateDate == date && worker.UpdateDate != date.AddDays(1) && worker.UpdateDate > date.AddDays(2) && worker.UpdateDate >= date.AddDays(3) && worker.UpdateDate < date.AddDays(4) && worker.UpdateDate <= date.AddDays(5);
            #endregion

            #region or
            //Expression<Func<Worker, bool>> expression = worker => (worker.Id != 2 || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Id != id || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Id != temp.Id || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Id != Config.Id || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => ((worker.Id != 2 || worker.Id > 3) && worker.Id == 1) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => ((worker.Id != id || worker.Id > id) && worker.Id == 1) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => ((worker.Id != temp.Id || worker.Id > 3) && worker.Id == 1) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => ((worker.Id != Config.Id || worker.Id > 3) && worker.Id == 1) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => (worker.Name != name|| worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Name != temp.Name || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Name != Config.Name || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => (worker.Name != Config.GetName("1") || worker.Id > 3) && worker.Id == 1;
            //Expression<Func<Worker, bool>> expression = worker => ((worker.Name != name|| worker.Id > 3) && worker.Id == 1) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == 1 && (worker.Id != 2 || worker.Id > 3) || (worker.Id >= 4 && worker.Id < 5);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == id && (worker.Id != id + 1 || worker.Id > id + 2) || (worker.Id >= id + 3 && worker.Id < id + 4);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == temp.Id && (worker.Id != temp.Id + 1 || worker.Id > temp.Id + 2) || (worker.Id >= temp.Id + 3 && worker.Id < temp.Id + 4);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && (worker.Id != Config.Id + 1 || worker.Id > Config.Id + 2) || (worker.Id >= Config.Id + 3 && worker.Id < Config.Id + 4);
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && worker.Address.Contains("one");
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && (worker.Address.Contains(Config.Name) || worker.Address.Contains(name));
            Expression<Func<Worker, bool>> expression = worker => (worker.Address.Contains(Config.Name) || worker.Address.Contains(name)) && worker.Id == Config.Id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && (worker.Address.Contains(null) || worker.Address.Contains(null));
            //Expression<Func<Worker, bool>> expression = worker => (worker.Address.Contains(null) || worker.Address.Contains(null)) && worker.Id == Config.Id;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == temp.Id && (worker.Address.Contains(Config.Name) || worker.Address.Contains(name)) && worker.Age == temp.Age;
            //Expression<Func<Worker, bool>> expression = worker => worker.Id == Config.Id && worker.Age == Config.Age && (worker.Address.Contains(Config.Name) || worker.Address.Contains(name));
            //Expression<Func<Worker, bool>> expression = worker => (worker.Address.Contains(Config.Name) || worker.Address.Contains(name)) && worker.Id == Config.Id && worker.Age == Config.Age;
            #endregion

            //IList<string> list1 = new List<string>() { "a'aa", "bbb", "ccc" };
            //IList<string> list2 = new List<string>() { "a'aa" + name, likeCondition, name };
            //IList<string> list3 = new List<string>() { "a'aa" + name, "222" + temp.Name, "333" + Config.Name };
            //IList<string> list4 = new List<string>() { "a'aa" + name, "222" + Config.GetName(name), "333" + new Config().InstanceGetName(name) };
            #region in
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(null);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { null, "", "aaa" });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { "a'aa", "bbb", "ccc" });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { "a'aa" + name, likeCondition, name });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { "a'aa" + name, "222" + temp.Name, "333" + Config.Name });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { "3'33" + new Config().InstanceGetName(name) });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(new List<string>() { "a'aa" + name, "222" + Config.GetName(name), "333" + new Config().InstanceGetName(name) });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(list1);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(list2);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(list3);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.In(list4);
            //Expression<Func<Worker, bool>> expression = worker => worker.Age.In(new List<int>() { 1, 2, 3 });
            //Expression<Func<Worker, bool>> expression = worker => worker.Age.In(new List<int>() { 1, id, id + 3 });
            #endregion

            #region not in
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(null);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(new List<string>() { });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(new List<string>() { null, "", "aaa" });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(new List<string>() { "aaa", "bbb", "ccc" });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(new List<string>() { "aaa" + name, "222" + Config.GetName(name), "333" + new Config().InstanceGetName(name) });
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(list1);
            //Expression<Func<Worker, bool>> expression = worker => worker.Name.NotIn(list4); 
            #endregion

            //string sql1 = expression.ToWhereNonParametric(false, true, "SqlServer");
            (string sql1, Dictionary<string, object> dict) = expression.ToWhereParametric(false, true, "SqlServer");
            Console.WriteLine(sql1);
            //string sql2 = expression.ToWhereNonParametric(false, true, "MySql");
            //(string sql2, Dictionary<string, object> dict02) = expression.ToWhereParametric(true, true, "MySql");
            //Console.WriteLine(sql2);

            //string mysql01 = expression01.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql01);
            //string mysql02 = expression02.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql02);
            //string mysql03 = expression03.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql03);
            //string mysql04 = expression04.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql04);
            //string mysql05 = expression05.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql05);
            //string mysql06 = expression06.ToWhereNonParametric(false, true, "MySql");
            //Console.WriteLine(mysql06);

            #region 测试算数运算符两端可以是哪些类型的数据
            //object obj = 1 + 2;
            //obj = 1 + 1.2f;
            //obj = 1 + 1.3;
            //obj = 1 + 1.4m;
            //obj = 1.4m + 'a';
            //obj = 1.4m + "a";
            //obj = 1.4m - 1;
            //obj = 1.8m % 1.6m; 
            #endregion

            Console.ReadKey();
        }
    }
}
